﻿using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace Tools
{
    public class GetHtml
    {

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_req"></param>
        /// <param name="uri"></param>
        /// <param name="content">FormUrlEncodedContent或StringContent</param>
        /// <param name="mode">get或post</param>
        /// <returns></returns>
        public static async Task<HttpContent> GetPostHtmlAsync<T>(Action<HttpClient> _req, Uri uri, T content, string mode = "post")
            where T : HttpContent
        {
            HttpClient request = new HttpClient();
            {
                request.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
                request.DefaultRequestHeaders.Add("UserAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0");
                request.DefaultRequestHeaders.Add("Accept-Encoding", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
            }
            _req?.Invoke(request);

            HttpResponseMessage rep = null;
            switch (mode.ToLower())
            {
                case "get":
                    rep = await request.GetAsync(uri, HttpCompletionOption.ResponseContentRead);
                    break;
                default:
                    rep = await request.PostAsync(uri, content);
                    break;
            }
            return rep.Content;
        }

        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="_req">对象委托，用来设置req的一些其他属性如HEAD</param>
        /// <param name="url">访问的地址</param>
        /// <param name="post">要POST的数据</param>
        /// <param name="inputcookie">传入的COOKIE</param>
        /// <param name="outputcookie">返回的COOKIE</param>
        /// <param name="OpenGzip">是否启用GZIP压缩 默认不启用</param>
        /// <param name="encoding">网页编码</param>
        /// <param name="prikey_path">证书地址</param>
        /// <param name="prikey_password">证书密钥</param>
        /// <returns></returns>
        public async static Task<Tuple<bool, byte[]>> GetHtmlFromUrlToBytesAsync(Action<HttpWebRequest> _req, string url, string post, CookieContainer inputcookie, CookieContainer outputcookie, bool OpenGzip = false, Encoding encoding = null)
        {
            List<byte> _ret_bytes = new List<byte>();
            if (encoding == null)
                encoding = Encoding.UTF8;
            byte[] bs = encoding.GetBytes(post);
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            if (_req != null)
            {
                _req(req);
                if (string.IsNullOrEmpty(req.ContentType))
                    req.ContentType = "application/x-www-form-urlencoded";
            }
            else
            {
                req.ContentType = "application/x-www-form-urlencoded";
            }

            if (!string.IsNullOrEmpty(post))
            {
                req.Method = "POST";
            }
            else
            {
                req.Method = "GET";
            }

            //req.Proxy = null;//不使用代理 .NET4.0中的默认代理是开启的

            req.ContinueTimeout = 5000;//连接网址的超时时间
                                       //req.ReadWriteTimeout = 5000;//读取网址内容的超时时间        


            req.CookieContainer = inputcookie ?? new CookieContainer();


            if (bs.Length > 0)
            {
                using (Stream reqStream = await req.GetRequestStreamAsync())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    await reqStream.FlushAsync();
                }
            }

            using (HttpWebResponse response = (HttpWebResponse)await req.GetResponseAsync())
            {
                if (OpenGzip)
                {
                    using (System.IO.Compression.GZipStream gzip_sm = new System.IO.Compression.GZipStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress))
                    {
                        int temp = gzip_sm.ReadByte();
                        while (temp != -1)
                        {
                            _ret_bytes.Add((byte)temp);
                            temp = gzip_sm.ReadByte();
                        }
                    }
                }
                else
                {
                    var res_steam = response.GetResponseStream();

                    int temp = res_steam.ReadByte();
                    while (temp != -1)
                    {
                        _ret_bytes.Add((byte)temp);
                        temp = res_steam.ReadByte();
                    }
                }

                if (outputcookie != null)
                {
                    foreach (Cookie cookie in response.Cookies)
                    {
                        outputcookie.Add(new Uri(url), cookie);
                    }
                }

                if (response != null)
                    response.Dispose();
            }
            if (req != null)
            {
                req.Abort();
                req = null;
            }

            return new Tuple<bool, byte[]>(true, _ret_bytes.ToArray());

        }


        /// <summary>
        /// 获取HTML
        /// </summary>
        /// <param name="_req">对象委托，用来设置req的一些其他属性如HEAD</param>
        /// <param name="url">访问的地址</param>
        /// <param name="post">要POST的数据</param>
        /// <param name="inputcookie">传入的COOKIE</param>
        /// <param name="outputcookie">返回的COOKIE</param>
        /// <param name="OpenGzip">是否启用GZIP压缩 默认不启用</param>
        /// <param name="encoding">网页编码</param>
        /// <param name="prikey_path">证书地址</param>
        /// <param name="prikey_password">证书密钥</param>
        /// <returns></returns>
        public async static Task<Tuple<bool, string>> GetHtmlFromUrlAsync(Action<HttpWebRequest> _req, string url, string post, CookieContainer inputcookie, CookieContainer outputcookie, bool OpenGzip = false, Encoding encoding = null, string prikey_path = "", string prikey_password = "")
        {
            string html = string.Empty;
            if (encoding == null)
                encoding = Encoding.UTF8;
            byte[] bs = encoding.GetBytes(post);
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            if (_req != null)
            {
                _req(req);
                if (string.IsNullOrEmpty(req.ContentType))
                    req.ContentType = "application/x-www-form-urlencoded";
            }
            else
            {
                req.ContentType = "application/x-www-form-urlencoded";
            }

            if (!string.IsNullOrEmpty(post))
            {
                req.Method = "POST";
                
            }
            //req.Proxy = null;//不使用代理 .NET4.0中的默认代理是开启的
            //req.ReadWriteTimeout = 5000;//读取网址内容的超时时间        



            req.CookieContainer = inputcookie ?? new CookieContainer();


            if (bs.Length > 0)
            {
                using (Stream reqStream = await req.GetRequestStreamAsync())
                {
                    reqStream.Write(bs, 0, bs.Length);
                    await reqStream.FlushAsync();
                }
            }

            using (HttpWebResponse response = (HttpWebResponse)await req.GetResponseAsync())
            {
                if (OpenGzip)
                {
                    using (System.IO.Compression.GZipStream gzip_sm = new System.IO.Compression.GZipStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress))
                    {
                        using (StreamReader reader = new StreamReader(gzip_sm, encoding))
                        {
                            html = reader.ReadToEnd().ToString();
                        }
                    }
                }
                else
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                    {
                        html = reader.ReadToEnd().ToString();
                    }
                }

                if (outputcookie != null)
                {
                    foreach (Cookie cookie in response.Cookies)
                    {
                        outputcookie.Add(new Uri(url), cookie);
                    }
                }

                if (response != null)
                    response.Dispose();


            }
            if (req != null)
            {
                req.Abort();
                req = null;
            }
            return new Tuple<bool, string>(true, html);
        }
    }
}